﻿using Sample1.MetaLang;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MetaLang
{
    public enum TokenType
    {
        /// <summary>
        /// 符号
        /// </summary>
        Symbol,
        /// <summary>
        /// 左括号
        /// </summary>
        LeftP,
        /// <summary>
        /// 右括号
        /// </summary>
        RightP,
        /// <summary>
        /// 分割符
        /// </summary>
        Seperator,
        /// <summary>
        /// 缩进符
        /// </summary>
        Indentation
    }
    public class MetaToken
    {
        public string code;
        /// <summary>
        /// 缩进次数
        /// </summary>
        public int? indentation;
        public TokenType type;
        /// <summary>
        /// 在代码中的索引位置
        /// </summary>
        public int? index;
        public int? line;
        public int? column;
    }
    public class MetaTokenParser
    {
        public const char Blank = ' ';
        public const char Enter = '\n';
        public char[] leftParenthesisChars = new char[] { '(','（' };
        public char[] rightParenthesisChars = new char[] { ')','）' };
        public char[] separatorChars = new char[] { ',','，' };
        public char[] specialChars = new char[] {'!','@','#','$','%','^','&','*','-','+','=',
            '.','*','\\','/','。','，',':',';','；','：','’','[',']','“','”','`','·','~','"',
            '>','<','《','》','{','}', };

        public List<MetaToken> Parser(string code)
        {
            List<MetaToken> res = new List<MetaToken>();
            int index = 0;
            int NextUnBlank()
            {
                int nextIndex = index + 1;
                while (code[nextIndex] == Blank)
                    nextIndex++;
                return nextIndex;
            }
            while (true)
            {
                char ch = code[index];
                CompileHelper.GetLineColumn(code, index, out int line, out int col);
                if (ch == Blank)
                {
                    //首行是空格。其他情况不会有空格
                    int blankEnd = NextUnBlank();
                    //空白行不用对齐继续
                    if (code[blankEnd] == '\n')
                        continue;
                    //未对齐
                    if ((blankEnd - index) % 4 != 0)
                    {
                        throw new Exception($"行:{line},列{col}缩进不是4的倍数");
                    }
                    res.Add(new MetaToken {
                        code= code.Substring(index,blankEnd-index),
                        index= index,
                        column= col,
                        line= line,
                        indentation=(blankEnd-index)/4,
                        type=TokenType.Seperator,
                    });
                    index = blankEnd;
                }
                else if (ch==Enter)
                {
                    int endindex=NextUnBlank();
                    res.Add(new MetaToken {
                        
                    });
                    index=endindex;
                }
                else if (leftParenthesisChars.Contains(ch))
                {
                    res.Add(new MetaToken {
                        code=ch.ToString(),
                        index=index,
                        line=line,
                        column=col,
                        type= TokenType.LeftP,
                    });
                }
                else if (rightParenthesisChars.Contains(ch))
                {
                    res.Add(new MetaToken
                    {
                        code = ch.ToString(),
                        index = index,
                        line = line,
                        column = col,
                        type = TokenType.RightP,
                    });
                }
                else if (separatorChars.Contains(ch))
                {
                    res.Add(new MetaToken
                    {
                        code = ch.ToString(),
                        index = index,
                        line = line,
                        column = col,
                        type = TokenType.Seperator,
                    });
                }
                else if (specialChars.Contains(ch))
                {
                    res.Add(new MetaToken
                    {
                        code = ch.ToString(),
                        index = index,
                        line = line,
                        column = col,
                        type = TokenType.Symbol,
                    });
                }
            }

            return res;
        }
    }
    public class MetaAstNode
    {
        public List<MetaAstNode> elements;
        public string symbol;
        public MetaAstNode parent;
        public static MetaAstNode Parser(string code)
        {
            MetaAstNode res = null;
            
            return res;
        }
        public bool IsSymbol
        {
            get
            {
                if (symbol == null == (elements == null))
                    throw new Exception("token无法判定类型");
                return elements == null;
            }
        }
        public bool IsList => !IsSymbol;
        public bool IsRoot => parent == null;
    }
    /// <summary>
    /// 编译环节
    /// </summary>
    public interface ICompilePhase
    {
        public string Name { set; get; }
        public Type inputType { get; set; }
        public Type outputType { get; set; }
        public Func<object, object> Excute { set; get; }
    }
    public class CompilePhase<TIn, TOut> : ICompilePhase
    {
        public string Name { set; get; }
        public Type inputType { get; set; } = typeof(TIn);
        public Type outputType { get; set; } = typeof(TOut);
        Func<object,object> ICompilePhase.Excute{ set { } get => (o) => Excute((TIn)o); }
        public new Func<TIn, TOut> Excute { set; get; }
    }
    public class MetaLangCompiler
    {
        public List<ICompilePhase> phases;
        public MetaLangCompiler()
        {
            phases = new List<ICompilePhase>() {
                new CompilePhase<string,string>() {
                    Name="统一换行符,制表符转4空格",
                    Excute=s=>s.ToString().Replace(Environment.NewLine,"\n").Replace("\t","    ")
                },
                new CompilePhase<string,List<MetaToken>>()
                {
                    Name="token分析",
                    Excute=new MetaTokenParser().Parser
                },
            };
        }
        public string Compile(string code)
        {
            return code;
        }
    }
}
